1
|
|
|
/* jshint curly:false, forin:false, expr:true */ |
2
|
|
|
;(function( window, document, undefined ) { |
3
|
|
|
"use strict"; |
4
|
|
|
|
5
|
|
|
var Plugin = function( el, options ) |
6
|
|
|
{ |
7
|
|
|
this.el = el; |
8
|
|
|
this.options = options; |
9
|
|
|
this.expanded = false; |
10
|
|
|
this.isAnimating = false; |
11
|
|
|
this.positions = ['top','left','bottom','right']; |
12
|
|
|
|
13
|
|
|
this.init(); |
14
|
|
|
}; |
15
|
|
|
|
16
|
|
|
Plugin.prototype = |
17
|
|
|
{ |
18
|
|
|
defaults: { |
19
|
|
|
openEl: ".morph-open", |
20
|
|
|
closeEl: ".morph-close", |
21
|
|
|
contentEl: ".morph-content", |
22
|
|
|
onAfterClose: null, |
23
|
|
|
onAfterOpen: null, |
24
|
|
|
onBeforeClose: null, |
25
|
|
|
onBeforeOpen: null, |
26
|
|
|
}, |
27
|
|
|
|
28
|
|
|
init: function() |
29
|
|
|
{ |
30
|
|
|
this.config = castor._extend( {}, this.defaults, this.options, this.el.getAttribute( 'data-options' )); |
|
|
|
|
31
|
|
|
|
32
|
|
|
this.openEl = this.el.querySelector( this.config.openEl ); |
33
|
|
|
this.closeEl = this.el.querySelector( this.config.closeEl ); |
34
|
|
|
this.contentEl = this.el.querySelector( this.config.contentEl ); |
35
|
|
|
|
36
|
|
|
this.transitionEndListener = this.transitionEnd.bind( this ); |
37
|
|
|
|
38
|
|
|
this.el.classList.add( 'can-morph' ); |
39
|
|
|
|
40
|
|
|
this.openEl.addEventListener( 'click', this.toggle.bind( this )); |
41
|
|
|
document.addEventListener( 'keyup', this.keypress.bind( this )); |
42
|
|
|
|
43
|
|
|
if( this.closeEl ) { |
44
|
|
|
this.closeEl.addEventListener( 'click', this.toggle.bind( this )); |
45
|
|
|
} |
46
|
|
|
|
47
|
|
|
return this; |
48
|
|
|
}, |
49
|
|
|
|
50
|
|
|
callback: function( callback ) |
51
|
|
|
{ |
52
|
|
|
if( typeof this.config[ callback ] === 'function' ) { |
53
|
|
|
this.config[ callback ]( this.el ); |
54
|
|
|
} |
55
|
|
|
}, |
56
|
|
|
|
57
|
|
|
keypress: function( ev ) |
58
|
|
|
{ |
59
|
|
|
if( 27 === ( ev.keyCode || ev.which ) && this.expanded ) { |
60
|
|
|
this.toggle(); |
61
|
|
|
} |
62
|
|
|
}, |
63
|
|
|
|
64
|
|
|
toggle: function( ev ) |
65
|
|
|
{ |
66
|
|
|
if( ev !== undefined ) { |
67
|
|
|
ev.preventDefault(); |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
if( this.isAnimating )return; |
|
|
|
|
71
|
|
|
|
72
|
|
|
this.isAnimating = true; |
73
|
|
|
|
74
|
|
|
this.contentEl.addEventListener( castor._getTransitionEvent(), this.transitionEndListener ); |
|
|
|
|
75
|
|
|
|
76
|
|
|
this.el.classList.add( 'active' ); |
77
|
|
|
|
78
|
|
|
this.expanded ? this.close() : this.open(); |
79
|
|
|
}, |
80
|
|
|
|
81
|
|
|
open: function() |
82
|
|
|
{ |
83
|
|
|
document.body.classList.add( 'opened-morph' ); |
84
|
|
|
|
85
|
|
|
this.callback( 'onBeforeOpen' ); |
86
|
|
|
|
87
|
|
|
this.setPosition( this.getCoordinates()); |
88
|
|
|
}, |
89
|
|
|
|
90
|
|
|
close: function() |
91
|
|
|
{ |
92
|
|
|
this.callback( 'onBeforeClose' ); |
93
|
|
|
|
94
|
|
|
this.setPosition( this.getCoordinates()); |
95
|
|
|
|
96
|
|
|
document.body.classList.remove( 'opened-morph' ); |
97
|
|
|
this.el.classList.remove( 'open' ); |
98
|
|
|
|
99
|
|
|
(new AnimationFrame()).request( function() { |
|
|
|
|
100
|
|
|
this.contentEl.classList.remove( 'no-transition' ); |
101
|
|
|
this.setPosition( 0 ); |
102
|
|
|
}.bind( this )); |
103
|
|
|
}, |
104
|
|
|
|
105
|
|
|
transitionEnd: function( ev ) |
106
|
|
|
{ |
107
|
|
|
if( ev.target !== this.contentEl )return; |
|
|
|
|
108
|
|
|
|
109
|
|
|
if( !this.expanded && -1 === this.positions.indexOf( ev.propertyName ))return; |
|
|
|
|
110
|
|
|
|
111
|
|
|
this.isAnimating = false; |
112
|
|
|
|
113
|
|
|
this.contentEl.removeEventListener( castor._getTransitionEvent(), this.transitionEndListener ); |
|
|
|
|
114
|
|
|
|
115
|
|
|
if( !this.expanded ) { |
116
|
|
|
this.contentEl.classList.add( 'no-transition' ); |
117
|
|
|
|
118
|
|
|
(new AnimationFrame()).request( function() { |
|
|
|
|
119
|
|
|
this.el.classList.add( 'open' ); |
120
|
|
|
this.el.classList.remove( 'active' ); |
121
|
|
|
}.bind( this )); |
122
|
|
|
} |
123
|
|
|
else { |
124
|
|
|
this.el.classList.remove( 'active' ); |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
this.callback( this.expanded ? 'onAfterClose' : 'onAfterOpen' ); |
128
|
|
|
|
129
|
|
|
this.expanded = !this.expanded; |
130
|
|
|
}, |
131
|
|
|
|
132
|
|
|
getCoordinates: function() |
133
|
|
|
{ |
134
|
|
|
var coordinates = this.el.getClientRects()[0]; |
135
|
|
|
|
136
|
|
|
return { |
137
|
|
|
top: -(coordinates.top) + 'px', |
138
|
|
|
left: -(coordinates.left) + 'px', |
139
|
|
|
bottom: -(window.innerHeight - coordinates.bottom) + 'px', |
140
|
|
|
right: -(window.innerWidth - coordinates.right) + 'px', |
141
|
|
|
}; |
142
|
|
|
}, |
143
|
|
|
|
144
|
|
|
setPosition: function( coordinates ) |
145
|
|
|
{ |
146
|
|
|
this.positions.forEach( function( position ) { |
147
|
|
|
this.contentEl.style[ position ] = ( coordinates === Object( coordinates )) ? coordinates[ position ] : coordinates; |
148
|
|
|
}.bind( this )); |
149
|
|
|
}, |
150
|
|
|
}; |
151
|
|
|
|
152
|
|
|
Plugin.defaults = Plugin.prototype.defaults; |
153
|
|
|
|
154
|
|
|
castor.MorphContent = Plugin; |
|
|
|
|
155
|
|
|
|
156
|
|
|
})( window, document ); |
157
|
|
|
|
This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.
To learn more about declaring variables in Javascript, see the MDN.